﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Lincolnwood.Foundation.Scheduling;
using Lincolnwood.Foundation.Scheduling.Data;
using Lincolnwood.Foundation.Common;
using Lincolnwood.Foundation.Scheduling.Data.NHibernate;
using NHibernate;
using Lincolnwood.Foundation.Common.Data.NHibernate;
using Lincolnwood.Foundation.Common.Data;

namespace Lincolnwood.Foundation.Scheduling.Tests
{
    [TestClass]
    public class SchedulingServiceTests
    {

        private NHibernateHelper _nHibernateHelper = new NHibernateHelper();
        private IUnitOfWork _unitOfWork;

        public SchedulingServiceTests()
        {
            _nHibernateHelper.ConfigureWith(typeof(NHibernateEventsRepository).Assembly);
        }

        [TestInitialize]
        public void TestInitialize()
        {
            _nHibernateHelper.GenerateSchema();
            _unitOfWork = new NHibernateSchedulingUnitOfWork();

        }

        [TestMethod]
        public void ScheduleNewNonRecurringEvent_Succeeds()
        {

            IEventsRepository mockEventsRepository = new NHibernateEventsRepository(_unitOfWork);
            IScheduleRepository mockScheduleRepository = new NHibernateScheduleRepository(_unitOfWork);

            SchedulingService scheduleService = new SchedulingService(mockScheduleRepository, mockEventsRepository);

            Schedule testSchedule = scheduleService.CreateSchedule(new Account(), "Test Schedule");
            _unitOfWork.Flush();


            RecurrableEventDefinition testEventDefinition = scheduleService.CreateEvent(
                testSchedule,
                "Test Event",
                "This is a test event",
                DateTime.Parse("1/1/2000 2:00 pm"),
                DateTime.Parse("1/1/2000 3:00 pm"));

            scheduleService.ScheduleEvent(testEventDefinition);

            _unitOfWork.Flush();
        }

        [TestMethod]
        public void ScheduleAndRetrieveNonRecurringEvent_Succeeds()
        {

            IEventsRepository eventsRepository = new NHibernateEventsRepository(_unitOfWork);
            IScheduleRepository scheduleRepository = new NHibernateScheduleRepository(_unitOfWork);

            SchedulingService scheduleService = new SchedulingService(scheduleRepository, eventsRepository);

            Schedule testSchedule = scheduleService.CreateSchedule(new Account(), "Test Schedule");

            RecurrableEventDefinition testEventDefinition = scheduleService.CreateEvent(
                testSchedule,
                "Test Event",
                "This is a test event",
                DateTime.Parse("1/1/2000 2:00 pm"),
                DateTime.Parse("1/1/2000 3:00 pm"));

            scheduleService.ScheduleEvent(testEventDefinition);

            _unitOfWork.Flush();

            /*************************/

            Guid savedEventId = testEventDefinition.Id;


            RecurrableEventDefinition retrievedEventDefinition = scheduleService.GetEventDefinitionById(savedEventId);

            Assert.AreEqual<Guid>(savedEventId, retrievedEventDefinition.Id);
            Assert.AreEqual<string>(testEventDefinition.Name, retrievedEventDefinition.Name);
            Assert.AreEqual<string>(testEventDefinition.Description, retrievedEventDefinition.Description);
            Assert.AreEqual<DateTime>(testEventDefinition.StartTime, retrievedEventDefinition.StartTime);
            Assert.AreEqual<DateTime>(testEventDefinition.EndTime, retrievedEventDefinition.EndTime);
        }

        [TestMethod]
        public void ScheduleDailyRecurringEvent_Succeeds()
        {

            IEventsRepository eventsRepository = new NHibernateEventsRepository(_unitOfWork);
            IScheduleRepository scheduleRepository = new NHibernateScheduleRepository(_unitOfWork);

            SchedulingService scheduleService = new SchedulingService(scheduleRepository, eventsRepository);

            Schedule testSchedule = scheduleService.CreateSchedule(new Account(), "Test Schedule");

            RecurrableEventDefinition testEventDefinition = scheduleService.CreateEvent(
                testSchedule,
                "Test Event",
                "This is a test event",
                DateTime.Parse("1/1/2000 2:00 pm"),
                DateTime.Parse("1/1/2000 3:00 pm"));

            testEventDefinition.SetMonthlyRecurrence(DateTime.Parse("12/15/2000"), 1);

            scheduleService.ScheduleEvent(testEventDefinition);

            _unitOfWork.Flush();

          
        }

        [TestMethod]
        public void ScheduleDailyRecurringEventThenModifyOne_Succeeds()
        {

            IEventsRepository eventsRepository = new NHibernateEventsRepository(_unitOfWork);
            IScheduleRepository scheduleRepository = new NHibernateScheduleRepository(_unitOfWork);

            SchedulingService scheduleService = new SchedulingService(scheduleRepository, eventsRepository);

            Schedule testSchedule = scheduleService.CreateSchedule(new Account(), "Test Schedule");

            RecurrableEventDefinition testEventDefinition = scheduleService.CreateEvent(
                testSchedule,
                "Test Event",
                "This is a test event",
                DateTime.Parse("1/1/2000 2:00 pm"),
                DateTime.Parse("1/1/2000 3:00 pm"));

            testEventDefinition.SetMonthlyRecurrence(DateTime.Parse("12/15/2000"), 1);

            scheduleService.ScheduleEvent(testEventDefinition);

            _unitOfWork.Flush();

            /*************************/

            Guid savedEventId = testEventDefinition.Id;


            IList<IEventInstance> retrievedEvents = scheduleService.GetEvents(DateTime.Parse("1/1/2000 1:00 pm"),  DateTime.Parse("1/1/2005 2:00 pm"));

            Assert.AreEqual<int>(12, retrievedEvents.Count);

            foreach (IEventInstance eventItem in retrievedEvents)
            {
                Assert.AreEqual<string>(testEventDefinition.Name, eventItem.Name);
                Assert.AreEqual<string>(testEventDefinition.Description, eventItem.Description);
                Assert.AreEqual<bool>(testEventDefinition.IsRecurring, true);                
            }

            IEventInstance instanceToReschedule = retrievedEvents[2];

            RecurrableEventDefinition parentEventDefinition = instanceToReschedule.ParentEventDefinition;

            //if (!parentEventDefinition.Recurrence.TryFindPatternDeviationFor(instanceToReschedule.StartTime))
            //{
            //    parentEventDefinition.Recurrence.AlterInstance(instanceToReschedule.StartTime, "Altered Event", "Altered event description text", DateTime.Parse("2/1/2000 3:00"), DateTime.Parse("2/1/2000 5:00"));
            //}
            //else
            //{
            //    throw new Exception(String.Format("Shouldn't find a Pattern Deviation for {0}", instanceToReschedule.StartTime.ToLongDateString()));
            //}

            // reschedule the 2nd event instance only

            // modify non-recurring event

            // modify event series for recurring event

            // modify single instance of recurring event series


        }
    }
}
